a11y: Allow storing list of references in GtkAccessibleValue
authorEmmanuele Bassi <ebassi@gnome.org>
Wed, 22 Jul 2020 12:07:36 +0000 (13:07 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Sun, 26 Jul 2020 19:31:15 +0000 (20:31 +0100)
It's one of the fundamental accessible value types in ARIA.

gtk/gtkaccessiblevalue.c
gtk/gtkaccessiblevalueprivate.h

index 4ccd8a837d4161f1551fcc94d9a576de0cf5dd4b..dd155425ca658dfb19b51a0d065c55b35deb7bd6 100644 (file)
@@ -462,6 +462,125 @@ gtk_reference_accessible_value_get (const GtkAccessibleValue *value)
   return self->ref;
 }
 
+typedef struct {
+  GtkAccessibleValue parent;
+
+  GList *refs;
+} GtkReferenceListAccessibleValue;
+
+static void
+remove_weak_ref_from_list (gpointer  data,
+                           GObject  *old_reference)
+{
+  GtkReferenceListAccessibleValue *self = data;
+
+  GList *item = g_list_find (self->refs, old_reference);
+
+  if (item != NULL)
+    {
+      self->refs = g_list_remove_link (self->refs, item);
+      g_list_free (item);
+    }
+}
+
+static void
+gtk_reference_list_accessible_value_finalize (GtkAccessibleValue *value)
+{
+  GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
+
+  for (GList *l = self->refs; l != NULL; l = l->next)
+    {
+      if (l->data != NULL)
+        g_object_weak_unref (G_OBJECT (l->data), remove_weak_ref_from_list, self);
+    }
+
+  g_list_free (self->refs);
+}
+
+static gboolean
+gtk_reference_list_accessible_value_equal (const GtkAccessibleValue *value_a,
+                                           const GtkAccessibleValue *value_b)
+{
+  const GtkReferenceListAccessibleValue *self_a = (GtkReferenceListAccessibleValue *) value_a;
+  const GtkReferenceListAccessibleValue *self_b = (GtkReferenceListAccessibleValue *) value_b;
+
+  if (g_list_length (self_a->refs) != g_list_length (self_b->refs))
+    return FALSE;
+
+  for (GList *l = self_a->refs; l != NULL; l = l->next)
+    {
+      if (g_list_find (self_b->refs, l->data) == NULL)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+gtk_reference_list_accessible_value_print (const GtkAccessibleValue *value,
+                                           GString                  *buffer)
+{
+  const GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
+
+  if (self->refs == NULL)
+    {
+      g_string_append (buffer, "<null>");
+      return;
+    }
+
+  for (GList *l = self->refs; l != NULL; l = l->next)
+    {
+      g_string_append_printf (buffer, "%s<%p>",
+                              G_OBJECT_TYPE_NAME (l->data),
+                              l->data);
+    }
+}
+
+static const GtkAccessibleValueClass GTK_REFERENCE_LIST_ACCESSIBLE_VALUE = {
+  .type = GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE_LIST,
+  .type_name = "GtkReferenceListAccessibleValue",
+  .instance_size = sizeof (GtkReferenceListAccessibleValue),
+  .finalize = gtk_reference_list_accessible_value_finalize,
+  .equal = gtk_reference_list_accessible_value_equal,
+  .print = gtk_reference_list_accessible_value_print,
+};
+
+/*< private >
+ * gtk_reference_list_accessible_value_new:
+ * @value: (element-type GtkAccessible) (transfer full): a list of accessible objects
+ *
+ * Creates a new #GtkAccessible that stores a list of references to #GtkAccessible objects.
+ *
+ * Returns: (transfer full): the newly created #GtkAccessible
+ */
+GtkAccessibleValue *
+gtk_reference_list_accessible_value_new (GList *value)
+{
+  GtkAccessibleValue *res = gtk_accessible_value_alloc (&GTK_REFERENCE_LIST_ACCESSIBLE_VALUE);
+
+  GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) res;
+
+  self->refs = g_list_copy (value);
+  if (self->refs != NULL)
+    {
+      for (GList *l = self->refs; l != NULL; l = l->next)
+        g_object_weak_ref (l->data, remove_weak_ref_from_list, self);
+    }
+
+  return res;
+}
+
+GList *
+gtk_reference_list_accessible_value_get (const GtkAccessibleValue *value)
+{
+  GtkReferenceListAccessibleValue *self = (GtkReferenceListAccessibleValue *) value;
+
+  g_return_val_if_fail (value != NULL, 0);
+  g_return_val_if_fail (value->value_class == &GTK_REFERENCE_LIST_ACCESSIBLE_VALUE, 0);
+
+  return self->refs;
+}
+
 /* }}} */
 
 /* {{{ Collection API */
@@ -490,6 +609,9 @@ typedef enum {
   /* reference */
   GTK_ACCESSIBLE_COLLECT_REFERENCE,
 
+  /* references list */
+  GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST,
+
   /* allows collecting GTK_ACCESSIBLE_VALUE_UNDEFINED; implied
    * by GTK_ACCESSIBLE_COLLECT_TRISTATE
    */
@@ -765,7 +887,8 @@ typedef GtkAccessibleValue * (* GtkAccessibleValueTristateCtor) (int value);
 typedef GtkAccessibleValue * (* GtkAccessibleValueEnumCtor)     (int value);
 typedef GtkAccessibleValue * (* GtkAccessibleValueNumberCtor)   (double value);
 typedef GtkAccessibleValue * (* GtkAccessibleValueStringCtor)   (const char *value);
-typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor)      (gpointer value);
+typedef GtkAccessibleValue * (* GtkAccessibleValueRefCtor)      (GtkAccessible *value);
+typedef GtkAccessibleValue * (* GtkAccessibleValueRefListCtor)  (GList *value);
 
 /*< private >
  * gtk_accessible_value_get_default_for_state:
@@ -917,8 +1040,8 @@ gtk_accessible_value_collect_valist (const GtkAccessibleCollect *cstate,
 
     case GTK_ACCESSIBLE_COLLECT_REFERENCE:
       {
-        GtkAccessibleValueStringCtor ctor =
-          (GtkAccessibleValueStringCtor) cstate->ctor;
+        GtkAccessibleValueRefCtor ctor =
+          (GtkAccessibleValueRefCtor) cstate->ctor;
 
         gpointer value = va_arg (*args, gpointer);
 
@@ -929,6 +1052,20 @@ gtk_accessible_value_collect_valist (const GtkAccessibleCollect *cstate,
       }
       break;
 
+    case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
+      {
+        GtkAccessibleValueRefListCtor ctor =
+          (GtkAccessibleValueRefListCtor) cstate->ctor;
+
+        GList *value = va_arg (*args, gpointer);
+
+        if (ctor == NULL)
+          res = gtk_reference_list_accessible_value_new (value);
+        else
+          res = (* ctor) (value);
+      }
+      break;
+
     case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
     case GTK_ACCESSIBLE_COLLECT_INVALID:
     default:
@@ -1051,8 +1188,8 @@ gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate,
 
     case GTK_ACCESSIBLE_COLLECT_REFERENCE:
       {
-        GtkAccessibleValueStringCtor ctor =
-          (GtkAccessibleValueStringCtor) cstate->ctor;
+        GtkAccessibleValueRefCtor ctor =
+          (GtkAccessibleValueRefCtor) cstate->ctor;
 
         gpointer value = g_value_get_object (value_);
 
@@ -1063,6 +1200,20 @@ gtk_accessible_value_collect_value (const GtkAccessibleCollect *cstate,
       }
       break;
 
+    case GTK_ACCESSIBLE_COLLECT_REFERENCE_LIST:
+      {
+        GtkAccessibleValueRefListCtor ctor =
+          (GtkAccessibleValueRefListCtor) cstate->ctor;
+
+        GList *value = g_value_get_pointer (value_);
+
+        if (ctor == NULL)
+          res = gtk_reference_list_accessible_value_new (value);
+        else
+          res = (* ctor) (value);
+      }
+      break;
+
     case GTK_ACCESSIBLE_COLLECT_UNDEFINED:
     case GTK_ACCESSIBLE_COLLECT_INVALID:
     default:
@@ -1236,7 +1387,7 @@ gtk_accessible_value_get_default_for_relation (GtkAccessibleRelation relation)
     case GTK_ACCESSIBLE_RELATION_FLOW_TO:
     case GTK_ACCESSIBLE_RELATION_LABELLED_BY:
     case GTK_ACCESSIBLE_RELATION_OWNS:
-      return NULL;
+      return gtk_undefined_accessible_value_new ();
 
     /* Integers */
     case GTK_ACCESSIBLE_RELATION_COL_COUNT:
index 30648d1fb0c9dcc9ffbcbbe0771552230467f2f5..9405c872ef0233b520c2709b1702b42e897dd4dd 100644 (file)
@@ -42,7 +42,8 @@ typedef enum {
   GTK_ACCESSIBLE_VALUE_TYPE_INTEGER,
   GTK_ACCESSIBLE_VALUE_TYPE_NUMBER,
   GTK_ACCESSIBLE_VALUE_TYPE_STRING,
-  GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE
+  GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE,
+  GTK_ACCESSIBLE_VALUE_TYPE_REFERENCE_LIST
 } GtkAccessibleValueType;
 
 struct _GtkAccessibleValue
@@ -130,6 +131,9 @@ const char *                    gtk_string_accessible_value_get         (const G
 GtkAccessibleValue *            gtk_reference_accessible_value_new      (GtkAccessible            *value);
 GtkAccessible *                 gtk_reference_accessible_value_get      (const GtkAccessibleValue *value);
 
+GtkAccessibleValue *            gtk_reference_list_accessible_value_new (GList                    *value);
+GList *                         gtk_reference_list_accessible_value_get (const GtkAccessibleValue *value);
+
 /* Token values */
 GtkAccessibleValue *            gtk_invalid_accessible_value_new        (GtkAccessibleInvalidState value);
 GtkAccessibleInvalidState       gtk_invalid_accessible_value_get        (const GtkAccessibleValue *value);